package com.tgy;

import com.tgy.util.AbstractList;

/**
 * @Author: tgy
 * @Date: 2020-09-07 09:14
 */
public class LinkedList<E> extends AbstractList<E> {

    private Node<E> firstNode;

    private Node<E> lastNode;


    private static class Node<E>{

        private E element;

        private Node<E> next;

        private Node<E> pre;

        public Node(Node<E> pre, E element, Node<E> next) {

            this.pre = pre;
            this.element = element;
            this.next = next;
        }
    }

    @Override
    public E get(int index) {

        return nodeOf(index).element;
    }

    @Override
    public E set(int index, E element) {

        Node<E> deleteNode = nodeOf(index);


        Node<E> replaceNode = new Node<>(deleteNode.pre, element, deleteNode.next);

        if (deleteNode.pre == null) {

            firstNode = replaceNode;
        }else {

            deleteNode.pre.next = replaceNode;
        }

        if (deleteNode.next == null) {

            lastNode = replaceNode;
        }else {

            deleteNode.next.pre = replaceNode;
        }


        return deleteNode.element;
    }

    @Override
    public void add(int index, E element) {


        if (index == size) {

            // 往最后插入元素

            Node<E> newNode = new Node<>(lastNode, element, null);

            if (lastNode != null) {

                lastNode.next = newNode;
            }
            lastNode = newNode;

            if (firstNode == null) {

                firstNode = lastNode;
            }

            size++;
            return;
        }

        Node<E> nextNode = nodeOf(index);

        Node<E> newNode = new Node<>(nextNode.pre, element, nextNode);

        if (newNode.pre == null) {

            firstNode = newNode;
        }else {

            newNode.pre.next = newNode;
        }

        nextNode.pre = newNode;

        size++;
    }

    @Override
    public E remove(int index) {

        Node<E> deleteNode = nodeOf(index);

        if (deleteNode.pre == null) {

            firstNode = deleteNode.next;
        }else {

            deleteNode.pre.next = deleteNode.next;
        }


        if (deleteNode.next == null) {

            lastNode = deleteNode.pre;
        }else {

            deleteNode.next.pre = deleteNode.pre;
        }

        size--;
        return deleteNode.element;
    }

    @Override
    public int indexof(E element) {

//        判断是否为null
        Node<E> tmpNode = null;

        if (element == null) {

            for (int i = 0; i < size; i++) {

                if (i == 0) {

                    tmpNode = firstNode;
                }

                if (tmpNode.element == element) {

                    return i;
                }

                tmpNode = tmpNode.next;
            }

        }else {


            for (int i = 0; i < size; i++) {

                if (i == 0) {

                    tmpNode = firstNode;
                }

                if (element.equals(tmpNode.element)) {

                    return i;
                }
                tmpNode = tmpNode.next;
            }

        }

        return -1;
    }

    @Override
    public void clear() {

//        gc root
        firstNode = null;
        lastNode = null;
        size = 0;
    }

    @Override
    public String toString() {

        StringBuilder stringBuilder = new StringBuilder();

        stringBuilder.append("LinkedList size=").append(size).append(" {");

        Node<E> tmpNode = firstNode;
        for (int i = 0; i < size; i++) {

            if (i != 0) {

                stringBuilder.append(",");
            }

            if (tmpNode.element == null) {

                stringBuilder.append("null");
            }else {

                stringBuilder.append(tmpNode.element);
            }

            tmpNode = tmpNode.next;
        }

        stringBuilder.append("} ");
        return stringBuilder.toString();
    }

    private Node<E> nodeOf(int index) {

        checkIndex(index);

        Node<E> tmpNode = null;

        if (index < (size >> 1)) {

            for (int i = 0; i <= index; i++) {

                if (i == 0) {

                    tmpNode = firstNode;
                }else {

                    tmpNode = tmpNode.next;
                }
            }

        }else {

            for (int i = size - 1; i >= index ; i--) {

                if (i == (size -1)) {

                    tmpNode = lastNode;
                }else {

                    tmpNode = tmpNode.pre;
                }
            }
        }

        return tmpNode;
    }

}
